package com.lingjtx.common.captcha;

import com.alibaba.fastjson2.JSON;
import com.lingjtx.common.core.algorithm.Base64Util;
import com.lingjtx.common.core.util.CommonUtil;
import com.lingjtx.common.core.util.FileCopyUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ImageUtil {

    public static final Logger log = LoggerFactory.getLogger(ImageUtil.class);

    private static final Map<String, String> originalRotateCacheMap = new ConcurrentHashMap<>();  //旋转底图
    private static final Map<String, String> rotateBlockCacheMap = new ConcurrentHashMap<>(); //旋转块
    private static final Map<String, String> originalCacheMap = new ConcurrentHashMap<>();  //滑块底图
    private static final Map<String, String> slidingBlockCacheMap = new ConcurrentHashMap<>(); //滑块
    private static final Map<String, String> picClickCacheMap = new ConcurrentHashMap<>(); //点选文字
    private static final Map<String, String[]> fileNameMap = new ConcurrentHashMap<>();

    static {
        // 旋转拼图
//        originalRotateCacheMap.putAll(getResourcesImagesFile("images/rotate/original"));
//        rotateBlockCacheMap.putAll(getResourcesImagesFile("images/rotate/rotateBlock"));
        //滑动拼图
        originalCacheMap.putAll(getResourcesImagesFile("mv/original", 8));
        slidingBlockCacheMap.putAll(getResourcesImagesFile("mv/sliding", 6));
        //点选文字
        picClickCacheMap.putAll(getResourcesImagesFile("click", 12));

        fileNameMap.put(CaptchaBaseMapEnum.ORIGINAL.getCodeValue(), originalCacheMap.keySet().toArray(new String[0]));
        fileNameMap.put(CaptchaBaseMapEnum.SLIDING_BLOCK.getCodeValue(), slidingBlockCacheMap.keySet().toArray(new String[0]));
        fileNameMap.put(CaptchaBaseMapEnum.PIC_CLICK.getCodeValue(), picClickCacheMap.keySet().toArray(new String[0]));
        fileNameMap.put(CaptchaBaseMapEnum.ROTATE.getCodeValue(), originalRotateCacheMap.keySet().toArray(new String[0]));
        fileNameMap.put(CaptchaBaseMapEnum.ROTATE_BLOCK.getCodeValue(), rotateBlockCacheMap.keySet().toArray(new String[0]));
        log.info("初始化底图:{}", JSON.toJSONString(fileNameMap));
    }

    public static void cacheBootImage(Map<String, String> originalMap, Map<String, String> slidingBlockMap, Map<String, String> picClickMap) {
        originalCacheMap.putAll(originalMap);
        slidingBlockCacheMap.putAll(slidingBlockMap);
        picClickCacheMap.putAll(picClickMap);
        fileNameMap.put(CaptchaBaseMapEnum.ORIGINAL.getCodeValue(), originalCacheMap.keySet().toArray(new String[0]));
        fileNameMap.put(CaptchaBaseMapEnum.SLIDING_BLOCK.getCodeValue(), slidingBlockCacheMap.keySet().toArray(new String[0]));
        fileNameMap.put(CaptchaBaseMapEnum.PIC_CLICK.getCodeValue(), picClickCacheMap.keySet().toArray(new String[0]));
        log.info("自定义resource底图:{}", JSON.toJSONString(fileNameMap));
    }

    public static BufferedImage getRotate() {
        String[] strings = fileNameMap.get(CaptchaBaseMapEnum.ROTATE.getCodeValue());
        if (null == strings || strings.length == 0) {
            return null;
        }
        int randomInt = CommonUtil.randomScope(0, strings.length);
        String s = originalRotateCacheMap.get(strings[randomInt]);
        return getBase64StrToImage(s);
    }

    public static String getRotateBlock() {
        String[] strings = fileNameMap.get(CaptchaBaseMapEnum.ROTATE_BLOCK.getCodeValue());
        if (null == strings || strings.length == 0) {
            return null;
        }
        int randomInt = CommonUtil.randomScope(0, strings.length);
        return rotateBlockCacheMap.get(strings[randomInt]);
    }

    public static BufferedImage getOriginal() {
        String[] strings = fileNameMap.get(CaptchaBaseMapEnum.ORIGINAL.getCodeValue());
        if (null == strings || strings.length == 0) {
            return null;
        }
        int randomInt = CommonUtil.randomScope(0, strings.length);
        String s = originalCacheMap.get(strings[randomInt]);
        return getBase64StrToImage(s);
    }

    public static BufferedImage getBgByInternet() {
        try {
            URL url = new URL("https://picsum.photos/310/155");
            return ImageIO.read(url);
        } catch (IOException e) {
            return getOriginal();
        }
    }

    public static String getslidingBlock() {
        String[] strings = fileNameMap.get(CaptchaBaseMapEnum.SLIDING_BLOCK.getCodeValue());
        if (null == strings || strings.length == 0) {
            return null;
        }
        int randomInt = CommonUtil.randomScope(0, strings.length);
        return slidingBlockCacheMap.get(strings[randomInt]);
    }

    public static BufferedImage getPicClick() {
        String[] strings = fileNameMap.get(CaptchaBaseMapEnum.PIC_CLICK.getCodeValue());
        if (null == strings || strings.length == 0) {
            return null;
        }
        int randomInt = CommonUtil.randomScope(0, strings.length);
        String s = picClickCacheMap.get(strings[randomInt]);
        return getBase64StrToImage(s);
    }

    /**
     * 图片转base64 字符串
     *
     * @param templateImage
     * @return
     */
    public static String getImageToBase64Str(BufferedImage templateImage) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ImageIO.write(templateImage, "png", baos);
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] bytes = baos.toByteArray();

        Base64.Encoder encoder = Base64.getEncoder();

        return encoder.encodeToString(bytes).trim();
    }

    /**
     * base64 字符串转图片
     *
     * @param base64String
     * @return
     */
    public static BufferedImage getBase64StrToImage(String base64String) {
        try {
            Base64.Decoder decoder = Base64.getDecoder();
            byte[] bytes = decoder.decode(base64String);
            ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
            return ImageIO.read(inputStream);
        } catch (IOException e) {
            return null;
        }
    }


    private static Map<String, String> getResourcesImagesFile(String path, int n) {
        //默认提供六张底图
        Map<String, String> imgMap = new HashMap<>();
        ClassLoader classLoader = ImageUtil.class.getClassLoader();
        for (int i = 1; i <= n; i++) {
            InputStream resourceAsStream = classLoader.getResourceAsStream(path.concat("/").concat(String.valueOf(i).concat(".png")));
            try {
                byte[] bytes = FileCopyUtil.copyToByteArray(resourceAsStream);
                String string = Base64Util.encodeToString(bytes);
                String filename = String.valueOf(i).concat(".png");
                imgMap.put(filename, string);
            } catch (IOException ignored) {
            }
        }
        return imgMap;
    }

    private static Map<String, String> getImagesFile(String path) {
        Map<String, String> imgMap = new HashMap<>();
        File file = new File(path);
        if (!file.exists()) {
            return new HashMap<>();
        }
        File[] files = file.listFiles();
        assert files != null;
        Arrays.stream(files).forEach(item -> {
            try {
                FileInputStream fileInputStream = new FileInputStream(item);
                byte[] bytes = FileCopyUtil.copyToByteArray(fileInputStream);
                String string = Base64Util.encodeToString(bytes);
                imgMap.put(item.getName(), string);
            } catch (IOException ignored) {
            }
        });
        return imgMap;
    }

    private static int countFilesInResources(String folderPath) {
        // 获取资源文件夹的 URL
        URL resourceUrl = ImageUtil.class.getClassLoader().getResource(folderPath);
        if (resourceUrl == null) {
            return 0;
        }
        try {
            File resourceFolder = new File(resourceUrl.toURI());
            return countFilesRecursively(resourceFolder);
        } catch (URISyntaxException e) {
            return 0;
        }
    }

    private static int countFilesRecursively(File folder) {
        int fileCount = 0;

        File[] files = folder.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isFile()) {
                    fileCount++;
                } else if (file.isDirectory()) {
                    fileCount += countFilesRecursively(file);
                }
            }
        }
        return fileCount;
    }
}
